using System;
using System.Diagnostics;

using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;

namespace SiteParser.Core.Logging
{
    /// <summary>
    /// Outputs trace to console using different colors for different actions
    /// </summary>
    [ConfigurationElementType(typeof(CustomTraceListenerData))]
    public class ConsoleTraceListener : CustomTraceListener
    {
        public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
        {
            if (data is LogEntry && Formatter != null)
            {
                WriteLine(Formatter.Format(data as LogEntry), data as LogEntry);
            }
            else
            {
                WriteLine(data.ToString(), data as LogEntry);
            }
        }

        public override void Write(string message)
        {
            Write(message, null);
        }

        public override void WriteLine(string message)
        {
            Write(message, null);
        }

        internal static void Write(string message, LogEntry entry)
        {
            lock (colorSyncRoot)
            {
                ConsoleColor oldColor = SelectColor(entry);
                Console.Out.Write(message);
                Console.ForegroundColor = oldColor;
            }
        }

        internal static void WriteLine(string message, LogEntry entry)
        {
            lock (colorSyncRoot)
            {
                ConsoleColor oldColor = SelectColor(entry);
                Console.Out.WriteLine(message);
                Console.ForegroundColor = oldColor;
            }
        }

        private static ConsoleColor SelectColor(LogEntry entry)
        {
            ConsoleColor oldColor = Console.ForegroundColor;
            ConsoleColor newColor = ConsoleColor.Gray;

            if (entry != null)
            {
                switch (entry.Severity)
                {
                    case TraceEventType.Critical:
                    case TraceEventType.Error:
                        newColor = ConsoleColor.Red;
                        break;

                    case TraceEventType.Warning:
                        newColor = ConsoleColor.Yellow;
                        break;

                    case TraceEventType.Start:
                    case TraceEventType.Stop:
                        newColor = ConsoleColor.Cyan;
                        break;

                    default:
                        newColor = ConsoleColor.Gray;
                        break;
                }
            }

            Console.ForegroundColor = newColor;
            return oldColor;
        }

        static readonly object colorSyncRoot = new Object();
    }

}
